include(ForceIncludeHeader)

file(GLOB_RECURSE algorithms_srcs_cxx *.cpp)
file(GLOB_RECURSE algorithms_srcs_cuda *.cu)
set(solar_algorithms_cuda_with_thrust_srcs "shared/tool/analyzeResultData/CudaResultAnalysis.cu;analytical_model/io/csv/WriteFluxMap.cu;analytical_model/algorithm/pipeline/Utils.cu;analytical_model/algorithm/cuda/evaluation/metrics/RAD.cu;analytical_model/algorithm/cuda/evaluation/metrics/WRAD.cu;analytical_model/algorithm/cuda/ConvolutionMethod.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/shared/tool/analyzeResultData/CudaResultAnalysis.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/analytical_model/io/csv/WriteFluxMap.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/analytical_model/algorithm/pipeline/Utils.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/analytical_model/algorithm/cuda/evaluation/metrics/RAD.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/analytical_model/algorithm/cuda/evaluation/metrics/WRAD.cu")
list(REMOVE_ITEM algorithms_srcs_cuda "${CMAKE_SOURCE_DIR}/source/algorithm/analytical_model/algorithm/cuda/ConvolutionMethod.cu")
add_library(solar_algorithms STATIC ${algorithms_srcs_cxx})
add_library(solar_algorithms_cuda STATIC ${algorithms_srcs_cuda})
add_library(solar_algorithms_cuda_with_thrust STATIC ${solar_algorithms_cuda_with_thrust_srcs})
target_include_directories(solar_algorithms PUBLIC "${CMAKE_SOURCE_DIR}/source")
target_include_directories(solar_algorithms PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories(solar_algorithms_cuda PUBLIC "${CMAKE_SOURCE_DIR}/source")
target_include_directories(solar_algorithms_cuda PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories(solar_algorithms_cuda_with_thrust PUBLIC "${CMAKE_SOURCE_DIR}/source")
target_include_directories(solar_algorithms_cuda_with_thrust PUBLIC ${Boost_INCLUDE_DIRS})

if(HAVE_STD_FORMAT)
    target_compile_definitions(solar_algorithms PUBLIC "HAVE_STD_FORMAT")
    target_compile_options(solar_algorithms PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
    if (CUDA20_SUPPORTED)
        target_compile_definitions(solar_algorithms_cuda PUBLIC "HAVE_STD_FORMAT")
        target_compile_options(solar_algorithms_cuda PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
        target_compile_definitions(solar_algorithms_cuda_with_thrust PUBLIC "HAVE_STD_FORMAT")
        target_compile_options(solar_algorithms_cuda_with_thrust PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
    endif()
else()
    find_package(fmt REQUIRED)
    target_link_libraries(solar_algorithms PUBLIC fmt::fmt)
    target_link_libraries(solar_algorithms_cuda PUBLIC fmt::fmt)
endif()

if(HAVE_STD_PRINT)
    target_compile_definitions(solar_algorithms PUBLIC "HAVE_STD_PRINT")
    target_compile_options(solar_algorithms PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
    if (CUDA23_SUPPORTED)
        target_compile_definitions(solar_algorithms_cuda PUBLIC "HAVE_STD_PRINT")
        target_compile_options(solar_algorithms_cuda PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
        target_compile_definitions(solar_algorithms_cuda_with_thrust PUBLIC "HAVE_STD_PRINT")
        target_compile_options(solar_algorithms_cuda_with_thrust PUBLIC "${STD_FORMAT_EXTRA_FLAGS}")
    endif()
endif()
find_package(PNG REQUIRED)
find_package(TBB REQUIRED)
find_package(OpenVINO REQUIRED)

try_compile(
    HAVE_ONEAPI_TBB
    "${CMAKE_SOURCE_DIR}/cmake"
    "${CMAKE_SOURCE_DIR}/cmake/try_compile_oneapi_tbb.cpp"
    COMPILE_DEFINITIONS "${TRY_COMPILE_STD_CXX_FLAGS}"
    OUTPUT_VARIABLE TRY_COMPILE_OUTPUT
    LINK_LIBRARIES TBB::tbb
)

if(NOT HAVE_ONEAPI_TBB)
    message(FATAL_ERROR "OneAPI TBB is not found")
endif()

try_compile(
    HAVE_OPENVINO
    "${CMAKE_SOURCE_DIR}/cmake"
    "${CMAKE_SOURCE_DIR}/cmake/try_compile_openvino.cpp"
    COMPILE_DEFINITIONS "${TRY_COMPILE_STD_CXX_FLAGS}"
    OUTPUT_VARIABLE TRY_COMPILE_OUTPUT
    LINK_LIBRARIES openvino::runtime
)

if(NOT HAVE_OPENVINO)
    message(FATAL_ERROR "OpenVINO is considered not found, maybe you should provide a newer version")
endif()

set_property(TARGET solar_algorithms_cuda PROPERTY CUDA_SEPARABLE_COMPILATION OFF)
set_property(TARGET solar_algorithms_cuda_with_thrust PROPERTY CUDA_SEPARABLE_COMPILATION OFF)
target_compile_definitions(solar_algorithms_cuda PRIVATE "SOLAR_CUDA_STANDALONE_COMPILE")
target_compile_definitions(solar_algorithms_cuda_with_thrust PRIVATE "SOLAR_CUDA_STANDALONE_COMPILE")
target_link_libraries(solar_algorithms PRIVATE VectorClass2)
target_link_libraries(solar_algorithms PRIVATE PNG::PNG)
target_link_libraries(solar_algorithms PRIVATE glad)
target_link_libraries(solar_algorithms PRIVATE CUDA::cudart)
target_link_libraries(solar_algorithms PRIVATE TBB::tbb)
target_link_libraries(solar_algorithms PRIVATE TBB::tbbmalloc)
target_link_libraries(solar_algorithms PRIVATE openvino::runtime)
target_link_libraries(solar_algorithms PRIVATE gcem)
#target_link_libraries(solar_algorithms_cuda PRIVATE strf-header-only)
#target_link_libraries(solar_algorithms_cuda PRIVATE strf-static-lib)
#target_link_libraries(solar_algorithms_cuda PRIVATE strf-cuda)
#target_link_libraries(solar_algorithms_cuda PRIVATE cuda-kat)
target_link_libraries(solar_algorithms_cuda PRIVATE glad)
target_link_libraries(solar_algorithms_cuda PRIVATE gcem)
target_link_libraries(solar_algorithms_cuda PRIVATE TBB::tbb)
target_link_libraries(solar_algorithms_cuda PRIVATE TBB::tbbmalloc)
target_link_libraries(solar_algorithms_cuda PRIVATE openvino::runtime)
force_include_header(solar_algorithms_cuda CUDA "${CMAKE_SOURCE_DIR}/source/utils/cuda/CudaWrappers.h")
force_include_header(solar_algorithms_cuda_with_thrust CUDA "${CMAKE_SOURCE_DIR}/source/utils/cuda/CudaWrappers.h")
#target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE strf-header-only)
#target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE strf-static-lib)
#target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE strf-cuda)
#target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE cuda-kat)
target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE glad)
target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE gcem)
target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE TBB::tbb)
target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE TBB::tbbmalloc)
target_link_libraries(solar_algorithms_cuda_with_thrust PRIVATE openvino::runtime)
if(MSVC)
    if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
        target_compile_definitions(solar_algorithms PRIVATE alloca=__builtin_alloca)
    else()
        target_compile_definitions(solar_algorithms PRIVATE alloca=_alloca)
    endif()
endif()

if(${CMAKE_CUDA_COMPILER_ID} MATCHES "Clang")
    # set_source_files_properties(analytical_model/algorithm/pipeline/Utils.cu analytical_model/algorithm/cuda/grid/RectangleGrid.cu analytical_model/algorithm/cuda/ShadowBlockCalculator.cu analytical_model/algorithm/cuda/evaluation/metrics/RAD.cu analytical_model/algorithm/cuda/evaluation/metrics/WRAD.cu analytical_model/algorithm/cuda/ConvolutionMethod.cu PROPERTIES COMPILE_FLAGS "-fno-lto -fno-whole-program-vtables")
endif()
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
    # set_source_files_properties(analytical_model/algorithm/pipeline/AnalyticalPipeline.cpp PROPERTIES COMPILE_FLAGS "-fno-lto -fno-whole-program-vtables -mllvm -fast-isel")
endif()